#ifndef PAGE_H
#define PAGE_H

#include <cstring>   // for memcpy, memset
#include <cstddef>   // for size_t
#include <atomic>    // for thread-safe pin counting
#include <functional>
#include"common.h"

// using page_id_t = int32_t;
// 定义无效页ID常量，通常用-1表示无效页
//constexpr page_id_t INVALID_PAGE_ID = 0;

// 定义默认页大小（4KB）
// constexpr size_t PAGE_SIZE = 4096;

/**
 * @brief 页ID类型定义
 * 使用有符号整数类型，方便使用-1作为无效值
 */


/**
 * @brief 页类，表示数据库中的一个数据页
 * 包含页头元数据和实际数据存储区
 */
class Page {
public:
    /**
     * @brief 默认构造函数
     * 创建一个空的、无效的页
     */
    Page();

    /**
     * @brief 构造函数，创建指定页ID的页
     * @param page_id 页的唯一标识符
     */
    explicit Page(page_id_t page_id);

    /**
     * @brief 析构函数
     */
    ~Page() = default;

    // 禁用拷贝构造函数和拷贝赋值（页应通过智能指针共享）
    Page(const Page&) = delete;
    Page& operator=(const Page&) = delete;

    /**
     * @brief 获取页ID
     * @return 页的唯一标识符
     */
    page_id_t get_page_id() const;

    /**
     * @brief 设置页ID
     * @param page_id 新的页ID
     */
    void set_page_id(page_id_t page_id);

    /**
     * @brief 获取页数据的原始指针，只读
     * @return 指向页数据区的常量指针
     */
    const char* get_data() const;

    /**
     * @brief 获取页数据的可修改指针
     * @return 指向页数据区的指针
     */
    char* get_data();

    /**
     * @brief 获取页数据的大小
     * @return 页数据区大小（PAGE_SIZE - 页头大小）
     */
    size_t get_data_size() const;

    /**
     * @brief 检查页是否为脏页（已被修改）
     * @return true如果是脏页，false否则
     */
    bool is_dirty() const;

    /**
     * @brief 标记页为脏页
     */
    void mark_dirty();

    /**
     * @brief 标记页为干净页
     */
    void mark_clean();

    /**
     * @brief 增加pin计数（页正在被使用）
     * @return 新的pin计数值
     */
    int pin_count();

    /**
     * @brief 减少pin计数（页使用结束）
     * @return 新的pin计数值
     */
    int unpin_count();

    /**
     * @brief 获取当前pin计数
     * @return pin计数值
     */
    int get_pin_count() const;

    /**
     * @brief 检查页是否被pin（是否正在被使用）
     * @return true如果pin计数>0，false否则
     */
    bool is_pinned() const;

    /**
     * @brief 重置页状态
     * 清除所有数据，重置为初始状态
     */
    void reset();

    /**
     * @brief 从另一个页复制数据
     * @param other 源页
     */
    void copy_from(const Page& other);

    /**
     * @brief 将数据复制到指定内存位置
     * @param dest 目标内存地址
     * @param size 要复制的字节数
     * @param offset 页内的偏移量
     * @return 实际复制的字节数
     */
    size_t copy_to(void* dest, size_t size, size_t offset = 0) const;

    /**
     * @brief 从指定内存位置复制数据到页
     * @param src 源内存地址
     * @param size 要复制的字节数
     * @param offset 页内的偏移量
     * @return 实际复制的字节数
     */
    size_t copy_from(const void* src, size_t size, size_t offset = 0);

    /**
     * @brief 比较两个页的数据是否相同
     * @param other 另一个页
     * @return true如果数据相同，false否则
     */
    bool data_equals(const Page& other) const;

private:
    /**
     * @brief 页头结构体
     * 包含页的元数据信息
     */
    struct PageHeader {
        page_id_t page_id = INVALID_PAGE_ID;  // 页的唯一标识符
        int32_t pin_count = 0;                // 页的引用计数（线程安全）
        bool is_dirty = false;                // 脏页标志
        uint32_t checksum = 0;                // 数据校验和（可选）
        uint16_t free_space_offset = 0;       // 空闲空间起始偏移（用于记录管理）
        uint16_t slot_count = 0;              // 槽数量（用于记录管理）
        // 可以添加更多元数据字段...
    };

    PageHeader header_;                    // 页头元数据
    char data_[PAGE_SIZE - sizeof(PageHeader)]; // 实际数据存储区

    // 静态断言，确保页总大小正确
    static_assert(sizeof(PageHeader) + sizeof(data_) == PAGE_SIZE, 
                 "Page size calculation error");
};

// 页的哈希函数，用于在unordered_map等容器中使用
struct PageHash {
    size_t operator()(const Page& page) const {
        return std::hash<page_id_t>()(page.get_page_id());
    }
};

// 页的相等比较函数
struct PageEqual {
    bool operator()(const Page& lhs, const Page& rhs) const {
        return lhs.get_page_id() == rhs.get_page_id();
    }
};

#endif // PAGE_H